package jnzb.ui.queue;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;

import jnzb.control.Controller;
import jnzb.model.queue.WaitingTableModel;
import jnzb.ui.table.JTableTT;

public class QueueControlPanel extends JPanel {

	private static final int COLUMNS_HIGH = 5;
	private static final int FIXED_COL_SIZE = 60;
	private JTable queueTable;
	private JButton up;
	private JButton down;
	private JButton remove;

	public QueueControlPanel() {
		create();
	}

	private void create() {
		Border etchedBorder = BorderFactory
				.createEtchedBorder(EtchedBorder.LOWERED);
		Border titleBorder = BorderFactory.createTitledBorder(etchedBorder,
				"Queued NZBs");
		this.setBorder(titleBorder);

		// Create a new BOLD version of the current font
		Font boldFont = new Font(super.getFont().getName(), Font.BOLD, super
				.getFont().getSize());

		this.setLayout(new BorderLayout());
		JLabel text = new JLabel(
				"Select an NZB then click the up/down arrow to re-order.");
		text.setHorizontalTextPosition(JLabel.LEFT);
		text.setHorizontalAlignment(JLabel.LEFT);
		Dimension size = text.getPreferredSize();
		size.setSize(size.getWidth(), size.getHeight() + 10);
		text.setPreferredSize(size);
		text.setMaximumSize(size);
		text.setMinimumSize(size);
		text.setSize(size);
		text.setFont(boldFont);
		this.add(text, BorderLayout.NORTH);

		JPanel tablePanel = createTablePanel();

		this.add(tablePanel, BorderLayout.CENTER);
	}

	private JPanel createTablePanel() {
		JPanel tablePanel = new JPanel();
		tablePanel.setLayout(new BoxLayout(tablePanel, BoxLayout.X_AXIS));

		// Create empty table
		queueTable = new JTableTT();
		// Dont need a header
		// queueTable.setTableHeader(null);
		queueTable.setAutoResizeMode(JTable.AUTO_RESIZE_LAST_COLUMN);

		// Set preferred viewport size to current width + set height
		Dimension currentPreferred = queueTable
				.getPreferredScrollableViewportSize();

		// Show COLUMNS_HIGH colummns in the viewport
		Dimension preferredHeight = new Dimension();
		preferredHeight.setSize(currentPreferred.getWidth(), queueTable
				.getRowHeight()
				* COLUMNS_HIGH);
		//
		// Set preferred viewable size
		queueTable.setPreferredScrollableViewportSize(preferredHeight);

		// Add table to scroll pane
		JScrollPane scrollPane;
		scrollPane = new JScrollPane(queueTable);

		// We have a border on the panel, so remove the border on the scroll
		// panel
		scrollPane.setBorder(BorderFactory.createEmptyBorder());

		// Create height that is the same as the scroll panel + header +
		// instruction label height + padding
		Dimension panelHeight = new Dimension();
		panelHeight.setSize(preferredHeight.getWidth(), preferredHeight
				.getHeight()
				+ queueTable.getRowHeight() + 14);

		tablePanel.add(scrollPane);
		tablePanel.add(createUpDown());
		tablePanel.add(Box.createVerticalGlue());

		
		return tablePanel;
	}

	private JPanel createUpDown() {
		JPanel buttonsPanel = new JPanel();
		buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.Y_AXIS));
		
		buttonsPanel.setAlignmentY(-1);

		up = new JButton("Move up");
		up.setAlignmentX(0.5f);
		buttonsPanel.add(up);

		down = new JButton("Move down");
		down.setAlignmentX(0.5f);
		buttonsPanel.add(down);

		remove = new JButton("Remove");
		remove.setAlignmentX(0.5f);
		buttonsPanel.add(remove);

		buttonsPanel.add(Box.createGlue());

		makeButtonWidthEqual(up, down, remove);
		
		// Ensure that this panel doesnt resize when the window does
		Dimension size = buttonsPanel.getPreferredSize();
		buttonsPanel.setMaximumSize(size);
		buttonsPanel.setMinimumSize(size);
		
		return buttonsPanel;
	}

	public static void makeButtonWidthEqual(JButton... buttons) {
		int maxWidth = Integer.MIN_VALUE;
		// First seach the button with the maximum width
		for (JButton button : buttons) {
			maxWidth = Math.max(maxWidth, button.getPreferredSize().width);
		}

		// Make all buttons that maximum width
		for (JButton button : buttons) {
			Dimension size = new Dimension(maxWidth,
					button.getPreferredSize().height);
			button.setPreferredSize(size);
			button.setMinimumSize(size);
			button.setMaximumSize(size);
		}
	}

	/**
	 * Links the button events to the controller
	 * 
	 * @param controller
	 */
	public void registerListeners(final Controller controller) {
		this.up.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// Fire action for anything but first row
				if (queueTable.getSelectedRow() > 0) {
					controller
							.queueControllUpEvent(queueTable.getSelectedRow());
				}
			}
		});

		this.down.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				
				if (queueTable.getSelectedRow() > -1 && (queueTable.getSelectedRow()+1)!=queueTable.getRowCount()) {
					controller.queueControllDownEvent(queueTable
							.getSelectedRow());
				}
			}
		});

		this.remove.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				if (queueTable.getSelectedRow() > -1) {
					controller.queueControllRemoveEvent(queueTable
							.getSelectedRow());
				}
			}
		});
	}

	/**
	 * Re-enable the queue control buttons. Meant to be called from outside of
	 * the UI as it runs in the swing thread
	 */
	public void enableButtons() {
		Runnable r = new Runnable() {
			@Override
			public void run() {
				setButtons(true);
			}
		};
		SwingUtilities.invokeLater(r);
	}

	/**
	 * Disbales all the queue control buttons (use while queue changes being
	 * effected). Meant to be called from outside of the UI as it runs in the
	 * swing thread
	 */
	public void disableButtons() {
		Runnable r = new Runnable() {
			@Override
			public void run() {
				setButtons(false);
			}
		};
		SwingUtilities.invokeLater(r);
	}

	private void setButtons(final boolean enabled) {
		up.setEnabled(enabled);
		down.setEnabled(enabled);
		remove.setEnabled(enabled);
	}

	public void setModel(WaitingTableModel model) {
		this.queueTable.setModel(model);
		resizeColumns();
	}

	/**
	 * Resizes the columns once the table model has been set
	 */
	private void resizeColumns(){
		// TODO - might be better to be relative to preferred size
		this.queueTable.getColumnModel().getColumn(1).setMaxWidth(FIXED_COL_SIZE);
		this.queueTable.getColumnModel().getColumn(2).setMaxWidth(FIXED_COL_SIZE);
	}
	
	/**
	 * Set the selected row
	 * @param rowNum
	 */
	public void setSelectedRow(int rowNum){
		this.queueTable.setRowSelectionInterval(rowNum, rowNum);
	}
}
